@file:Suppress("UnusedReceiverParameter")

package com.sscl.easyble.extensions

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Looper
import androidx.core.app.ActivityCompat
import com.sscl.easyble.variable.GlobalConnectVariable
import com.sscl.easyble.InternalConstants
import com.sscl.easyble.Logger
import java.util.concurrent.TimeUnit

private const val TAG = "InternalUtils"

/**
 * 检查BLUETOOTH_SCAN权限
 */
internal fun Any.hasBluetoothScanPermission(): Boolean {
    val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        val result = (ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.BLUETOOTH_SCAN,
        ) == PackageManager.PERMISSION_GRANTED) && ((ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.ACCESS_COARSE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED) || (ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED))
        result
    } else {
        val result = (ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.ACCESS_COARSE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED) || (ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED)
        result
    }
    if (!result) {
        Logger.log(TAG, "没有 BLUETOOTH_SCAN 权限 或 定位权限")
        Logger.log(TAG, "permission BLUETOOTH_SCAN  or LOCATION not granted")
    }
    return result
}

/**
 * 检查BLUETOOTH_CONNECT权限
 */
internal fun Any.hasBluetoothConnectPermission(): Boolean {
    val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        ActivityCompat.checkSelfPermission(
            InternalConstants.context, Manifest.permission.BLUETOOTH_CONNECT
        ) == PackageManager.PERMISSION_GRANTED
    } else {
        true
    }
    if (!result) {
        Logger.log(TAG, "没有 BLUETOOTH_CONNECT 权限")
        Logger.log(TAG, "permission BLUETOOTH_CONNECT not granted")
    }
    return result
}

/**
 *  停止连接超时定时器
 */
internal fun String.stopConnectTimeoutTimer() {
    Logger.log(TAG, "停止连接超时定时器:$this")
    Logger.log(TAG, "stop connect time out timer :$this")
    GlobalConnectVariable.connectTimeOutTimerList[this]?.shutdownNow()
    GlobalConnectVariable.connectTimeOutTimerList.remove(this)
}

/**
 * 启动连接超时定时器
 */
internal fun String.startConnectTimeoutTimer(connectTimeOut: Long, connectTimeOutUnit: TimeUnit) {
    stopConnectTimeoutTimer()
    val connectTimeoutTimer = InternalConstants.newScheduledThreadPoolExecutor()
    connectTimeoutTimer.schedule(
        {
            Logger.log(TAG, "连接超时:$this")
            Logger.log(TAG, "connect time out:$this")
            val onBleConnectStateChangedListener =
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList.remove(this)
            InternalConstants.handler.post {
                onBleConnectStateChangedListener?.connectTimeout(this)
            }
        }, connectTimeOut, connectTimeOutUnit
    )
    GlobalConnectVariable.connectTimeOutTimerList[this] = connectTimeoutTimer
    Logger.log(TAG, "启动连接超时定时器:$this")
    Logger.log(TAG, "start connect timer:$this")
}

internal fun Any.isMainThread(): Boolean {
    return Thread.currentThread() == Looper.getMainLooper().thread
}

/**
 * get total package count
 *
 * @return total package count
 */
internal fun ByteArray.getPageCount(singlePackMaxLength: Int): Int {
    val dataLength = this.size
    return if (dataLength % singlePackMaxLength == 0) {
        dataLength / singlePackMaxLength
    } else {
        dataLength / singlePackMaxLength + 1
    }
}


/**
 * get package data by specified index
 *
 * @param packageIndex index
 * @param pageCount    total count
 * @return packet data
 */
fun ByteArray.getCurrentPackageData(
    packageIndex: Int,
    pageCount: Int,
    singlePackMaxLength: Int
): ByteArray? {
    if (packageIndex >= pageCount) {
        return null
    }
    val largeDataLength = this.size
    return if (packageIndex == pageCount - 1) {
        val remainder: Int =
            largeDataLength % singlePackMaxLength
        val data = if (remainder == 0) {
            ByteArray(20)
        } else {
            ByteArray(remainder)
        }
        System.arraycopy(
            this,
            packageIndex * singlePackMaxLength,
            data,
            0,
            data.size
        )
        data
    } else {
        val data = ByteArray(20)
        System.arraycopy(
            this,
            packageIndex * singlePackMaxLength,
            data,
            0,
            data.size
        )
        data
    }
}